package com.ssy.lingxi.order.serviceimpl.base;

import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.basic.FundModeEnum;
import com.ssy.lingxi.common.constant.manage.ShopTypeEnum;
import com.ssy.lingxi.common.constant.order.*;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.bo.*;
import com.ssy.lingxi.order.model.constant.OrderFreightTypeEnum;
import com.ssy.lingxi.order.model.vo.basic.request.OrderSeparateProductVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderSeparateVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderSeparateVendorVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderPayChannelDetailVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderPayTypeDetailVO;
import com.ssy.lingxi.order.model.vo.common.request.OrderProductPriceTypeVO;
import com.ssy.lingxi.order.model.vo.common.response.OrderProductProcessQueryVO;
import com.ssy.lingxi.order.service.base.IBaseOrderProcessService;
import com.ssy.lingxi.order.service.feign.ISettleAccountFeignService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程规则配置、会员支付策略、会员支付参数查询接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-07-30
 */
@Service
public class BaseOrderProcessServiceImpl implements IBaseOrderProcessService {
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    @Resource
    private ISettleAccountFeignService settleAccountFeignService;


    /**
     * 校验采购订单（多供应商）合并下单条件
     *
     * @param separateVO 接口参数
     * @return 校验结果
     */
    @Override
    public Wrapper<Void> checkOrderMergeCondition(OrderSeparateVO separateVO) {
        //如果供应会员的个数为1，且订单商品数为1，正常下单
        List<VendorBO> vendors = separateVO.getVendors().stream().map(separate -> new VendorBO(separate.getVendorMemberId(), separate.getVendorRoleId())).collect(Collectors.toList());
        if(vendors.size() == 1 && separateVO.getVendors().stream().mapToLong(vendor -> vendor.getProducts().size()).sum() == 1) {
            return Wrapper.success();
        }

        //同一个供应商相同skuId不能下单
        for (OrderSeparateVendorVO separateVendor : separateVO.getVendors()) {
            if (separateVendor.getProducts().size() != separateVendor.getProducts().stream().map(OrderSeparateProductVO::getSkuId).collect(Collectors.toSet()).size()) {
                return Wrapper.fail(ResponseCode.ORDER_PRODUCT_SKU_IS_CHECK_SAME);
            }
        }

        //跨境商品与其他商品不能同时下单
        List<Boolean> crossBorders = separateVO.getVendors().stream().flatMap(vendor -> vendor.getProducts().stream()).map(OrderSeparateProductVO::getCrossBorder).distinct().collect(Collectors.toList());
        if(crossBorders.size() > 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        //Step 1: 运费方式（如有）必须为“卖家承担”
        if(vendors.size() > 1 && separateVO.getVendors().stream().flatMap(vendor -> vendor.getProducts().stream().map(product -> NumberUtil.isNullOrNegative(product.getFreightType()) ? OrderFreightTypeEnum.VENDOR.getCode() : product.getFreightType())).anyMatch(freightType -> !freightType.equals(OrderFreightTypeEnum.VENDOR.getCode()))) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_FREIGHT_TYPE_MUST_BE_VENDOR);
        }

        //Step 2: 查询资金归集模式
        Wrapper<List<PlatformPaymentDetailBO>> paymentResult = findPlatformMemberPayment(separateVO.getVendors().stream().map(separate -> new VendorBO(separate.getVendorMemberId(), separate.getVendorRoleId())).collect(Collectors.toList()));
        if(paymentResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(paymentResult.getCode(), paymentResult.getMessage());
        }

        //Step 3: 查询交易流程规则配置
        List<VendorProductBO> vendorProducts = separateVO.getVendors().stream().map(vendor -> {
            VendorProductBO productBO = new VendorProductBO();
            productBO.setVendorMemberId(vendor.getVendorMemberId());
            productBO.setVendorRoleId(vendor.getVendorRoleId());
            productBO.setProducts(vendor.getProducts().stream().map(p -> new OrderProductBO(p.getProductId(), p.getSkuId())).collect(Collectors.toList()));
            return productBO;
        }).collect(Collectors.toList());
        Wrapper<OrderTradeProcessBO> processResult = findVendorTradeProcess(separateVO.getShopId(), crossBorders.get(0) ? OrderTradeProcessTypeEnum.ORDER_COMMERCE_IMPORT : OrderTradeProcessTypeEnum.ORDER_TRADE, vendorProducts);
        if(processResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(processResult.getCode(), processResult.getMessage());
        }

        return Wrapper.success();
    }

    /**
     * （批量）查询供应商交易流程配置
     *
     * @param shopId               商城Id
     * @param tradeProcessTypeEnum 交易流程类型
     * @param vendorProducts       供应会员及商品信息列表
     * @return 查询结果
     */
    @Override
    public List<TradeProcessDetailBO> findVendorTradeProcessByProducts(Long shopId, OrderTradeProcessTypeEnum tradeProcessTypeEnum, List<VendorProductBO> vendorProducts) {
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;
        QOrderTradeProcessPaymentDO qOrderTradeProcessPayment = QOrderTradeProcessPaymentDO.orderTradeProcessPaymentDO;
        QOrderTradeProcessContractDO qOrderTradeProcessContract = QOrderTradeProcessContractDO.orderTradeProcessContractDO;

        // allProduct = false的情况：
        //    如果productId和skuId不匹配，不会出现 process 的配置
        // allProduct = true的情况
        //    即使多个productId和skuId不匹配，有且仅有一条 process 的配置，此时返回的ProductId和SkuId通过构造函数的Null值处理，变为0

        //Step 1: 拼接会员、商品Id、SkuId查询条件
        Predicate[] predicates = vendorProducts.stream().map(vendor -> {
            Predicate[] productPredicates = vendor.getProducts().stream().map(product -> qOrderTradeProcessProduct.productId.eq(product.getProductId()).and(qOrderTradeProcessProduct.skuId.eq(product.getSkuId()))).toArray(Predicate[]::new);
            return qOrderTradeProcess.memberId.eq(vendor.getVendorMemberId()).and(qOrderTradeProcess.roleId.eq(vendor.getVendorRoleId())).and(qOrderTradeProcess.allProducts.isTrue().or(ExpressionUtils.anyOf(productPredicates)));
        }).toArray(Predicate[]::new);

        return new ArrayList<>(jpaQueryFactory
                .from(qOrderTradeProcess)
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .leftJoin(qOrderTradeProcessPayment).on(qOrderTradeProcess.id.eq(qOrderTradeProcessPayment.process.id))
                .leftJoin(qOrderTradeProcessContract).on(qOrderTradeProcess.id.eq(qOrderTradeProcessContract.process.id))
                .where(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode()).and(qOrderTradeProcess.processType.eq(tradeProcessTypeEnum.getCode())).and(qOrderTradeProcess.shopId.eq(shopId)))
                .where(ExpressionUtils.anyOf(predicates))
                .transform(GroupBy.groupBy(qOrderTradeProcess.memberId, qOrderTradeProcess.roleId, qOrderTradeProcess.processKey, qOrderTradeProcess.allProducts, qOrderTradeProcessProduct.productId, qOrderTradeProcessProduct.skuId, qOrderTradeProcess.hasContract, qOrderTradeProcessContract.contractId, qOrderTradeProcess.expireHours).as(
                        Projections.constructor(TradeProcessDetailBO.class, qOrderTradeProcess.memberId, qOrderTradeProcess.roleId, qOrderTradeProcess.processKey, qOrderTradeProcess.processKind, qOrderTradeProcess.payTimes, qOrderTradeProcess.skipFirstStep, qOrderTradeProcess.allProducts, qOrderTradeProcessProduct.productId, qOrderTradeProcessProduct.skuId, qOrderTradeProcess.hasContract, qOrderTradeProcessContract.contractId, qOrderTradeProcess.expireHours,
                                GroupBy.list(Projections.constructor(PayNodeBO.class, qOrderTradeProcessPayment.serialNo, qOrderTradeProcessPayment.batchNo, qOrderTradeProcessPayment.payNode, qOrderTradeProcessPayment.payRate))
                        ))).values());
    }

    /**
     * 查询（供应）会员采购流程配置
     *
     * @param shopId               商城Id
     * @param tradeProcessTypeEnum 交易流程类型
     * @param vendorProducts       供应会员及商品信息列表
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderTradeProcessBO> findVendorTradeProcess(Long shopId, OrderTradeProcessTypeEnum tradeProcessTypeEnum, List<VendorProductBO> vendorProducts) {
        List<TradeProcessDetailBO> processDetails = findVendorTradeProcessByProducts(shopId, tradeProcessTypeEnum, vendorProducts);
        //Step 0: 如果查询结果为空，返回错误
        if(CollectionUtils.isEmpty(processDetails)) {
            return Wrapper.fail(ResponseCode.ORDER_VENDOR_DOES_NOT_CONFIG_TRADE_PROCESS);
        }

        //Step 1: 判断所有会员、商品是否查询到流程
        for (VendorProductBO vendorProduct : vendorProducts) {
            List<TradeProcessDetailBO> detailList = processDetails.stream().filter(detail -> detail.getVendorMemberId().equals(vendorProduct.getVendorMemberId()) && detail.getVendorRoleId().equals(vendorProduct.getVendorRoleId())).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(detailList)) {
                return Wrapper.fail(ResponseCode.ORDER_VENDOR_DOES_NOT_CONFIG_TRADE_PROCESS);
            }

            if(vendorProduct.getProducts().stream().anyMatch(product -> detailList.stream().noneMatch(detail -> detail.getAllProducts() || (detail.getProductId().equals(product.getProductId()) && detail.getSkuId().equals(product.getSkuId()))))) {
                return Wrapper.fail(ResponseCode.ORDER_VENDOR_TRADE_PROCESS_DOES_NOT_CONTAIN_PRODUCTS);
            }
        }

        //只有一个供应商，且只有一个商品时，不判断其他条件
        if(vendorProducts.size() == 1 && vendorProducts.stream().mapToLong(p -> p.getProducts().size()).sum() == 1) {
            return Wrapper.success(new OrderTradeProcessBO(processDetails));
        }

        //Step 2: 判断所有流程是否一致
        if(processDetails.stream().map(TradeProcessDetailBO::getProcessKey).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        //Step 3: 判断合同是否不一致（无合同时，合同Id等于0）
        if(processDetails.stream().map(TradeProcessDetailBO::getContractId).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        //Step 4: 判断订单取消时间是否一致
        if(processDetails.stream().map(TradeProcessDetailBO::getExpireHours).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        //Step 5: 判断支付次数是否一致
        if(processDetails.stream().map(TradeProcessDetailBO::getPayTimes).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        //Step 6: 判断支付环节名称、比例是否一致
        if(processDetails.stream().map(detail -> detail.getPayNodes().stream().sorted(Comparator.comparingInt(PayNodeBO::getBatchNo)).map(p -> p.getPayNode().concat(NumberUtil.formatPayRate(p.getPayRate()))).collect(Collectors.joining(""))).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_TRADE_PROCESS_IS_DIFFERENT);
        }

        return Wrapper.success(new OrderTradeProcessBO(processDetails));
    }

    /**
     * 查询（供应）会员交易流程配置
     *
     * @param vendorMemberId       供应会员Id
     * @param vendorRoleId         供应会员角色Id
     * @param shopId               商城Id
     * @param tradeProcessTypeEnum 交易流程类型
     * @param products             采购商品列表
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderTradeProcessBO> findVendorTradeProcess(Long vendorMemberId, Long vendorRoleId, Long shopId, OrderTradeProcessTypeEnum tradeProcessTypeEnum, List<OrderProductBO> products) {
        VendorProductBO vendorProduct = new VendorProductBO();
        vendorProduct.setVendorMemberId(vendorMemberId);
        vendorProduct.setVendorRoleId(vendorRoleId);
        vendorProduct.setProducts(products);

        return findVendorTradeProcess(shopId, tradeProcessTypeEnum, Collections.singletonList(vendorProduct));
    }

    /**
     * (转单）批量查询会员交易流程配置
     *
     * @param vendorProducts 订单Id、商城Id及供应会员、供应会员商品列表
     * @return 查询结果
     */
    @Override
    public Wrapper<Map<Long, OrderTradeProcessBO>> findVendorTradeProcess(List<OrderShopProductBO> vendorProducts) {
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;
        QOrderTradeProcessPaymentDO qOrderTradeProcessPayment = QOrderTradeProcessPaymentDO.orderTradeProcessPaymentDO;
        QOrderTradeProcessContractDO qOrderTradeProcessContract = QOrderTradeProcessContractDO.orderTradeProcessContractDO;

        // allProduct = false的情况：
        //    如果productId和skuId不匹配，不会出现 process 的配置
        // allProduct = true的情况
        //    即使多个productId和skuId不匹配，有且仅有一条 process 的配置，此时返回的ProductId和SkuId通过构造函数的Null值处理，变为0

        //Step 1: 拼接会员、商品Id、SkuId查询条件
        Predicate[] predicates = vendorProducts.stream().map(vendor -> {
            Predicate[] productPredicates = vendor.getProducts().stream().map(product -> qOrderTradeProcessProduct.productId.eq(product.getProductId()).and(qOrderTradeProcessProduct.skuId.eq(product.getSkuId()))).toArray(Predicate[]::new);
            return qOrderTradeProcess.memberId.eq(vendor.getVendorMemberId()).and(qOrderTradeProcess.roleId.eq(vendor.getVendorRoleId())).and(qOrderTradeProcess.shopId.eq(vendor.getShopId())).and(qOrderTradeProcess.allProducts.isTrue().or(ExpressionUtils.anyOf(productPredicates)));
        }).toArray(Predicate[]::new);

        List<TradeProcessDetailBO> processDetailList = new ArrayList<>(jpaQueryFactory
                .from(qOrderTradeProcess)
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .leftJoin(qOrderTradeProcessPayment).on(qOrderTradeProcess.id.eq(qOrderTradeProcessPayment.process.id))
                .leftJoin(qOrderTradeProcessContract).on(qOrderTradeProcess.id.eq(qOrderTradeProcessContract.process.id))
                .where(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode()).and(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode())))
                .where(ExpressionUtils.anyOf(predicates))
                .transform(GroupBy.groupBy(qOrderTradeProcess.memberId, qOrderTradeProcess.roleId, qOrderTradeProcess.processKey, qOrderTradeProcess.allProducts, qOrderTradeProcessProduct.productId, qOrderTradeProcessProduct.skuId, qOrderTradeProcess.hasContract, qOrderTradeProcessContract.contractId, qOrderTradeProcess.expireHours).as(
                        Projections.constructor(TradeProcessDetailBO.class, qOrderTradeProcess.memberId, qOrderTradeProcess.roleId, qOrderTradeProcess.processKey, qOrderTradeProcess.processKind, qOrderTradeProcess.payTimes, qOrderTradeProcess.skipFirstStep, qOrderTradeProcess.allProducts, qOrderTradeProcessProduct.productId, qOrderTradeProcessProduct.skuId, qOrderTradeProcess.hasContract, qOrderTradeProcessContract.contractId, qOrderTradeProcess.expireHours,
                                GroupBy.list(Projections.constructor(PayNodeBO.class, qOrderTradeProcessPayment.serialNo, qOrderTradeProcessPayment.batchNo, qOrderTradeProcessPayment.payNode, qOrderTradeProcessPayment.payRate))
                        ))).values());

        //Step 1: 判断所有会员、商品的交易流程
        Map<Long, OrderTradeProcessBO> processMap = new HashMap<>();
        for (OrderShopProductBO vendorProduct : vendorProducts) {
            List<TradeProcessDetailBO> processDetails = processDetailList.stream().filter(detail -> detail.getVendorMemberId().equals(vendorProduct.getVendorMemberId()) && detail.getVendorRoleId().equals(vendorProduct.getVendorRoleId())).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(processDetails)) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_DOES_NOT_CONFIG_TRADE_PROCESS);
            }

            if(vendorProduct.getProducts().stream().anyMatch(product -> processDetails.stream().noneMatch(detail -> detail.getAllProducts() || (detail.getProductId().equals(product.getProductId()) && detail.getSkuId().equals(product.getSkuId()))))) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_DOES_NOT_CONFIG_TRADE_PROCESS);
            }

            if(vendorProduct.getProducts().size() == 1) {
                processMap.put(vendorProduct.getOrderId(), new OrderTradeProcessBO(processDetails));
                continue;
            }

            //Step 2: 判断所有流程是否一致
            if(processDetails.stream().map(TradeProcessDetailBO::getProcessKey).distinct().count() != 1) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_TRADE_PROCESSES_ARE_DIFFERENT);
            }

            //Step 3: 判断合同是否不一致（无合同时，合同Id等于0）
            if(processDetails.stream().map(TradeProcessDetailBO::getContractId).distinct().count() != 1) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_TRADE_PROCESSES_ARE_DIFFERENT);
            }

            //Step 5: 判断订单取消时间是否一致
            if(processDetails.stream().map(TradeProcessDetailBO::getExpireHours).distinct().count() != 1) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_TRADE_PROCESSES_ARE_DIFFERENT);
            }

            //Step 5: 判断支付次数是否一致
            if(processDetails.stream().map(TradeProcessDetailBO::getPayTimes).distinct().count() != 1) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_TRADE_PROCESSES_ARE_DIFFERENT);
            }

            //Step 6: 判断支付环节名称、比例是否一致
            if(processDetails.stream().map(detail -> detail.getPayNodes().stream().sorted(Comparator.comparingInt(PayNodeBO::getBatchNo)).map(p -> p.getPayNode().concat(NumberUtil.formatPayRate(p.getPayRate()))).collect(Collectors.joining(""))).distinct().count() != 1) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_TRADE_PROCESSES_ARE_DIFFERENT);
            }

            processMap.put(vendorProduct.getOrderId(), new OrderTradeProcessBO(processDetails));
        }

        return Wrapper.success(processMap);
    }

    /**
     * 查询（采购）会员采购流程配置
     *
     * @param buyerMemberId           采购会员Id
     * @param buyerRoleId             采购会员角色Id
     * @param purchaseProcessTypeEnum 采购流程类型
     * @param contractIds             合同Id列表
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderPurchaseProcessBO> findBuyerPurchaseProcess(Long buyerMemberId, Long buyerRoleId, OrderPurchaseProcessTypeEnum purchaseProcessTypeEnum, List<Long> contractIds) {
        QOrderPurchaseProcessDO qOrderPurchaseProcess = QOrderPurchaseProcessDO.orderPurchaseProcessDO;
        QOrderPurchaseProcessContractDO qOrderPurchaseProcessContract = QOrderPurchaseProcessContractDO.orderPurchaseProcessContractDO;

        OrderPurchaseProcessBO processBO = jpaQueryFactory.select(Projections.constructor(OrderPurchaseProcessBO.class, qOrderPurchaseProcess.processKey, qOrderPurchaseProcess.skipFirstStep, qOrderPurchaseProcess.processKind))
                .from(qOrderPurchaseProcess)
                .leftJoin(qOrderPurchaseProcessContract).on(qOrderPurchaseProcess.id.eq(qOrderPurchaseProcessContract.process.id))
                .where(qOrderPurchaseProcess.status.eq(EnableDisableStatus.ENABLE.getCode()).and(qOrderPurchaseProcess.memberId.eq(buyerMemberId)).and(qOrderPurchaseProcess.roleId.eq(buyerRoleId)).and(qOrderPurchaseProcess.processType.eq(purchaseProcessTypeEnum.getCode())))
                .where(qOrderPurchaseProcess.allContracts.isTrue().or(qOrderPurchaseProcessContract.contractId.in(contractIds)))
                .fetchFirst();

        if(processBO == null) {
            return Wrapper.fail(ResponseCode.ORDER_BUYER_DOES_NOT_CONFIG_PURCHASE_PROCESS);
        }

        return Wrapper.success(processBO);
    }

    /**
     * （批量）从平台后台的会员支付策略中，查询会员支付方式、支付渠道设置
     *
     * @param vendors 供应会员Id与角色Id列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<PlatformPaymentDetailBO>> findPlatformMemberPayment(List<VendorBO> vendors) {
        QPlatformPaymentDO qPlatformPayment = QPlatformPaymentDO.platformPaymentDO;
        QPlatformPaymentTypeDO qPlatformPaymentType = QPlatformPaymentTypeDO.platformPaymentTypeDO;
        QPlatformPaymentChannelDO qPlatformPaymentChannel = QPlatformPaymentChannelDO.platformPaymentChannelDO;
        QPlatformPaymentMemberDO qPlatformPaymentMember = QPlatformPaymentMemberDO.platformPaymentMemberDO;

        //Step 1: 拼接会员、商品Id、SkuId查询条件
        Predicate[] predicates = vendors.stream().map(vendor -> qPlatformPaymentMember.memberId.eq(vendor.getVendorMemberId()).and(qPlatformPaymentMember.roleId.eq(vendor.getVendorRoleId()))).toArray(Predicate[]::new);

        //Step 2: 投影查询
        List<PlatformPaymentDetailBO> paymentDetails = jpaQueryFactory.select(Projections.constructor(PlatformPaymentDetailBO.class, qPlatformPaymentMember.memberId, qPlatformPaymentMember.roleId, qPlatformPaymentType.payType, qPlatformPaymentChannel.payChannel, qPlatformPaymentType.fundMode))
                .from(qPlatformPaymentType)
                .leftJoin(qPlatformPayment).on(qPlatformPayment.id.eq(qPlatformPaymentType.payment.id))
                .leftJoin(qPlatformPaymentChannel).on(qPlatformPaymentType.id.eq(qPlatformPaymentChannel.payType.id))
                .leftJoin(qPlatformPaymentMember).on(qPlatformPayment.id.eq(qPlatformPaymentMember.payment.id))
                .where(qPlatformPayment.status.eq(EnableDisableStatus.ENABLE.getCode()))
                .where(qPlatformPayment.allMembers.isTrue().or(ExpressionUtils.anyOf(predicates)))
                .fetch();

        if(vendors.size() == 1) {
            return Wrapper.success(paymentDetails);
        }

        // 如果有会员没有设置支付策略，不能合并下单
        if(paymentDetails.stream().anyMatch(payment -> !payment.getVendorMemberId().equals(0L) || !payment.getVendorRoleId().equals(0L)) && vendors.stream().anyMatch(vendor -> paymentDetails.stream().noneMatch(payment -> payment.getVendorMemberId().equals(vendor.getVendorMemberId()) && payment.getVendorRoleId().equals(vendor.getVendorRoleId())))) {
            return Wrapper.fail(ResponseCode.ORDER_CAN_NOT_MERGE_CAUSE_OF_PAYMENT_NOT_SET);
        }

        // 如果所有的支付方式的归集模式不为“平台代收”，不能合并下单
        if(paymentDetails.stream().anyMatch(payment -> !payment.getFundMode().equals(FundModeEnum.PLATFORM_EXCHANGE.getCode()))) {
            return Wrapper.fail(ResponseCode.ORDER_MEMBER_FUND_MODE_MUST_BE_PLATFORM_EXCHANGE);
        }

        // 如果支付方式不一致，不能合并下单
        if(paymentDetails.stream().collect(Collectors.groupingBy(p -> new VendorBO(p.getVendorMemberId(), p.getVendorRoleId()))).values().stream().map(v -> v.stream().sorted(Comparator.comparingInt(PlatformPaymentDetailBO::getPayChannel)).map(c -> String.valueOf(c.getPayChannel())).collect(Collectors.joining(""))).distinct().count() != 1) {
            return Wrapper.fail(ResponseCode.ORDER_MEMBER_PAY_CHANNELS_CAN_NOT_BE_DIFFERENT);
        }

        return Wrapper.success(paymentDetails);
    }

    /**
     * 从平台后台的会员支付策略中，查询会员支付方式、支付渠道设置
     *
     * @param memberId 供应会员Id
     * @param roleId   供应会员角色Id
     * @return 查询结果
     */
    @Override
    public List<PlatformPayTypeBO> findPlatformMemberPayment(Long memberId, Long roleId) {
        QPlatformPaymentDO qPlatformPayment = QPlatformPaymentDO.platformPaymentDO;
        QPlatformPaymentTypeDO qPlatformPaymentType = QPlatformPaymentTypeDO.platformPaymentTypeDO;
        QPlatformPaymentChannelDO qPlatformPaymentChannel = QPlatformPaymentChannelDO.platformPaymentChannelDO;
        QPlatformPaymentMemberDO qPlatformPaymentMember = QPlatformPaymentMemberDO.platformPaymentMemberDO;

        return new ArrayList<>(jpaQueryFactory.from(qPlatformPaymentType).distinct()
                .leftJoin(qPlatformPayment).on(qPlatformPayment.id.eq(qPlatformPaymentType.payment.id))
                .leftJoin(qPlatformPaymentChannel).on(qPlatformPaymentType.id.eq(qPlatformPaymentChannel.payType.id))
                .leftJoin(qPlatformPaymentMember).on(qPlatformPayment.id.eq(qPlatformPaymentMember.payment.id))
                .where(qPlatformPayment.status.eq(EnableDisableStatus.ENABLE.getCode()))
                .where(qPlatformPayment.allMembers.isTrue().or(qPlatformPaymentMember.memberId.eq(memberId).and(qPlatformPaymentMember.roleId.eq(roleId))))
                .transform(GroupBy.groupBy(qPlatformPaymentType.id).as(
                        Projections.constructor(PlatformPayTypeBO.class, qPlatformPaymentType.fundMode, qPlatformPaymentType.payType, qPlatformPaymentType.payTypeName,
                                GroupBy.list(Projections.constructor(PlatformPayChannelBO.class, qPlatformPaymentChannel.payChannel, qPlatformPaymentChannel.payChannelName)))))
                .values());
    }

    /**
     * 从平台后台的会员支付策略中，查询会员支付方式、支付渠道设置，拼接结算支付
     *
     * @param buyerMemberId  采购会员Id
     * @param buyerRoleId    采购会员角色Id
     * @param vendorMemberId 供应会员Id
     * @param vendorRoleId   供应会员角色Id
     * @return 查询结果
     */
    @Override
    public List<PlatformPayTypeBO> findPlatformMemberPayment(Long buyerMemberId, Long buyerRoleId, Long vendorMemberId, Long vendorRoleId, boolean needCheckSettlementPayType) {
        QPlatformPaymentDO qPlatformPayment = QPlatformPaymentDO.platformPaymentDO;
        QPlatformPaymentTypeDO qPlatformPaymentType = QPlatformPaymentTypeDO.platformPaymentTypeDO;
        QPlatformPaymentChannelDO qPlatformPaymentChannel = QPlatformPaymentChannelDO.platformPaymentChannelDO;
        QPlatformPaymentMemberDO qPlatformPaymentMember = QPlatformPaymentMemberDO.platformPaymentMemberDO;

        List<PlatformPayTypeBO> platformPayTypes = new ArrayList<>(jpaQueryFactory.from(qPlatformPaymentType).distinct()
                .leftJoin(qPlatformPayment).on(qPlatformPayment.id.eq(qPlatformPaymentType.payment.id))
                .leftJoin(qPlatformPaymentChannel).on(qPlatformPaymentType.id.eq(qPlatformPaymentChannel.payType.id))
                .leftJoin(qPlatformPaymentMember).on(qPlatformPayment.id.eq(qPlatformPaymentMember.payment.id))
                .where(qPlatformPayment.status.eq(EnableDisableStatus.ENABLE.getCode()))
                .where(qPlatformPayment.allMembers.isTrue().or(qPlatformPaymentMember.memberId.eq(vendorMemberId).and(qPlatformPaymentMember.roleId.eq(vendorRoleId))))
                .transform(GroupBy.groupBy(qPlatformPaymentType.id).as(
                        Projections.constructor(PlatformPayTypeBO.class, qPlatformPaymentType.fundMode, qPlatformPaymentType.payType, qPlatformPaymentType.payTypeName,
                                GroupBy.list(Projections.constructor(PlatformPayChannelBO.class, qPlatformPaymentChannel.payChannel, qPlatformPaymentChannel.payChannelName)))))
                .values());

        //拼接结算支付
        if(needCheckSettlementPayType) {
            Wrapper<OrderPayTypeDetailVO> settlementResult = settleAccountFeignService.findSettlementPaySetting(buyerMemberId, buyerRoleId, vendorMemberId, vendorRoleId);
            if (settlementResult.getCode() == ResponseCode.SUCCESS.getCode() && Objects.nonNull(settlementResult.getData())) {
                platformPayTypes.add(new PlatformPayTypeBO(settlementResult.getData().getFundMode(), settlementResult.getData().getPayType(), settlementResult.getData().getPayTypeName(), settlementResult.getData().getPayChannels().stream().map(payChannel -> new PlatformPayChannelBO(payChannel.getPayChannel(), payChannel.getPayChannelName())).collect(Collectors.toList())));
            }
        }

        return platformPayTypes;
    }

    /**
     * 从平台后台的会员支付策略中，查询指定的支付渠道设置
     *
     * @param payChannel 支付渠道
     * @param memberId   会员Id
     * @param roleId     会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<PlatformPayTypeBO> findPlatformMemberPayment(Integer payChannel, Long memberId, Long roleId) {
        QPlatformPaymentDO qPlatformPayment = QPlatformPaymentDO.platformPaymentDO;
        QPlatformPaymentTypeDO qPlatformPaymentType = QPlatformPaymentTypeDO.platformPaymentTypeDO;
        QPlatformPaymentChannelDO qPlatformPaymentChannel = QPlatformPaymentChannelDO.platformPaymentChannelDO;
        QPlatformPaymentMemberDO qPlatformPaymentMember = QPlatformPaymentMemberDO.platformPaymentMemberDO;

        PlatformPayTypeBO platformPayType = jpaQueryFactory
                .select(Projections.constructor(PlatformPayTypeBO.class, qPlatformPaymentType.fundMode, qPlatformPaymentType.payType, qPlatformPaymentType.payTypeName, Projections.list(Projections.constructor(PlatformPayChannelBO.class, qPlatformPaymentChannel.payChannel, qPlatformPaymentChannel.payChannelName))))
                .from(qPlatformPaymentType)
                .leftJoin(qPlatformPayment).on(qPlatformPaymentType.payment.id.eq(qPlatformPayment.id))
                .leftJoin(qPlatformPaymentChannel).on(qPlatformPaymentType.id.eq(qPlatformPaymentChannel.payType.id))
                .leftJoin(qPlatformPaymentMember).on(qPlatformPayment.id.eq(qPlatformPaymentMember.payment.id))
                .where(qPlatformPaymentChannel.payChannel.eq(payChannel))
                .where(qPlatformPayment.status.eq(EnableDisableStatus.ENABLE.getCode()))
                .where(qPlatformPayment.allMembers.isTrue().or(qPlatformPaymentMember.memberId.eq(memberId).and(qPlatformPaymentMember.roleId.eq(roleId))))
                .fetchFirst();

            return platformPayType == null ? Wrapper.fail(ResponseCode.ORDER_PAYMENT_SETTING_NOT_SET_YET) : Wrapper.success(platformPayType);
    }

    /**
     * 从平台后台的会员支付策略中，（批量）查询会员支付方式、支付渠道设置
     *
     * @param vendors 供应会员列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderPayTypeDetailVO>> findMemberPayment(Long buyerMemberId, Long buyerRoleId, List<VendorBO> vendors) {
        //如果只有一个供应商，拼接从资金账户服务查询到的结算支付方式
        if(vendors.size() == 1) {
            return findMemberPayment(buyerMemberId, buyerRoleId, vendors.get(0).getVendorMemberId(), vendors.get(0).getVendorRoleId());
        }

        Wrapper<List<PlatformPaymentDetailBO>> paymentResult = findPlatformMemberPayment(vendors);
        if(paymentResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(paymentResult.getCode(), paymentResult.getMessage());
        }

        //如果有多个供应商，资金归集模式必须是“平台代收”
        return Wrapper.success(paymentResult.getData().stream().collect(Collectors.groupingBy(PlatformPaymentDetailBO::getPayType)).entrySet().stream().map(entry -> new OrderPayTypeDetailVO(FundModeEnum.PLATFORM_EXCHANGE.getCode(), entry.getKey(), OrderPayTypeEnum.getNameByCode(entry.getKey()), entry.getValue().stream().map(PlatformPaymentDetailBO::getPayChannel).distinct().sorted(Comparator.comparingInt(Integer::intValue)).map(payChannel -> new OrderPayChannelDetailVO(payChannel, OrderPayChannelEnum.getNameByCode(payChannel))).collect(Collectors.toList()))).sorted(Comparator.comparingInt(OrderPayTypeDetailVO::getPayType)).collect(Collectors.toList()));
    }

    /**
     * 从平台后台的会员支付策略中，查询会员支付方式、支付渠道设置
     *
     * @param vendorMemberId 会员Id
     * @param vendorRoleId   会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderPayTypeDetailVO>> findMemberPayment(Long vendorMemberId, Long vendorRoleId) {
        //规则：
        // a. 平台后台“会员支付策略”过滤出平台代收模式、会员直接到账模式的支付渠道列表
        // b. 分别查询“平台支付参数设置”、“会员支付参数设置”中的支付方式与渠道，进行合并

        //Step 1: 查询平台后台会员支付策略
        List<PlatformPayTypeBO> platformPayTypes = findPlatformMemberPayment(vendorMemberId, vendorRoleId);
        if(CollectionUtils.isEmpty(platformPayTypes)) {
            return Wrapper.success(new ArrayList<>());
        }

        //Step 2: 查询平台支付参数设置
        QPlatformPaymentParameterDO qPlatformPaymentParameter = QPlatformPaymentParameterDO.platformPaymentParameterDO;
        List<PlatformPaymentParameterDO> platformParameters = jpaQueryFactory.select(qPlatformPaymentParameter).from(qPlatformPaymentParameter)
                .where(qPlatformPaymentParameter.payChannel.in(platformPayTypes.stream().filter(payType -> payType.getFundMode().equals(FundModeEnum.PLATFORM_EXCHANGE.getCode())).flatMap(payType -> payType.getChannels().stream().map(PlatformPayChannelBO::getPayChannel)).collect(Collectors.toList())))
                .fetch();

        List<OrderPayTypeDetailVO> platformTypes = platformParameters.stream().collect(Collectors.groupingBy(PlatformPaymentParameterDO::getPayType)).entrySet().stream().map(entry -> {
            OrderPayTypeDetailVO detailVO = new OrderPayTypeDetailVO();
            detailVO.setFundMode(FundModeEnum.PLATFORM_EXCHANGE.getCode());
            detailVO.setPayType(entry.getKey());
            detailVO.setPayTypeName(OrderPayTypeEnum.getNameByCode(entry.getKey()));
            detailVO.setPayChannels(entry.getValue().stream().map(parameter ->
                    new OrderPayChannelDetailVO(parameter.getPayChannel(), OrderPayChannelEnum.getNameByCode(parameter.getPayChannel()))
            ).sorted(Comparator.comparingInt(OrderPayChannelDetailVO::getPayChannel)).collect(Collectors.toList()));
            return detailVO;
        }).collect(Collectors.toList());

        //Step 3: 查询会员支付参数设置
        QMemberPaymentParameterDO qMemberPaymentParameter = QMemberPaymentParameterDO.memberPaymentParameterDO;
        List<MemberPaymentParameterDO> memberParameters = jpaQueryFactory
                .select(qMemberPaymentParameter).from(qMemberPaymentParameter)
                .where(qMemberPaymentParameter.memberId.eq(vendorMemberId).and(qMemberPaymentParameter.roleId.eq(vendorRoleId)).and(qMemberPaymentParameter.payChannel.in(platformPayTypes.stream().filter(payType -> payType.getFundMode().equals(FundModeEnum.DIRECT_TO_ACCOUNT.getCode())).flatMap(payType -> payType.getChannels().stream().map(PlatformPayChannelBO::getPayChannel)).collect(Collectors.toList()))))
                .fetch();

        List<OrderPayTypeDetailVO> memberTypes = memberParameters.stream().collect(Collectors.groupingBy(MemberPaymentParameterDO::getPayType)).entrySet().stream().map(entry -> {
            OrderPayTypeDetailVO detailVO = new OrderPayTypeDetailVO();
            detailVO.setFundMode(FundModeEnum.DIRECT_TO_ACCOUNT.getCode());
            detailVO.setPayType(entry.getKey());
            detailVO.setPayTypeName(OrderPayTypeEnum.getNameByCode(entry.getKey()));
            detailVO.setPayChannels(entry.getValue().stream().map(parameter ->
                    new OrderPayChannelDetailVO(parameter.getPayChannel(), OrderPayChannelEnum.getNameByCode(parameter.getPayChannel()))
            ).sorted(Comparator.comparingInt(OrderPayChannelDetailVO::getPayChannel)).collect(Collectors.toList()));
            return detailVO;
        }).collect(Collectors.toList());

        //Step 4: 合并
        platformTypes.addAll(memberTypes);

        //Step 5: 排序返回
        return Wrapper.success(platformTypes.stream().sorted(Comparator.comparingInt(OrderPayTypeDetailVO::getPayType)).collect(Collectors.toList()));
    }

    /**
     * 从平台后台的会员支付策略、与结算服务中，查询会员支付方式、支付渠道设置
     *
     * @param buyerMemberId  采购会员Id
     * @param buyerRoleId    采购会员角色Id
     * @param vendorMemberId 供应会员Id
     * @param vendorRoleId   供应会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderPayTypeDetailVO>> findMemberPayment(Long buyerMemberId, Long buyerRoleId, Long vendorMemberId, Long vendorRoleId) {
        //规则：
        // a. 平台后台“会员支付策略”过滤出平台代收模式、会员直接到账模式的支付渠道列表
        // b. 分别查询“平台支付参数设置”、“会员支付参数设置”中的支付方式与渠道，进行合并
        // c. 拼接从结算服务查询到的“账期”、“月结”的支付方式配置

        //Step 1: 从结算服务查询是否配置了“账期”与“月结”的支付方式
        Wrapper<OrderPayTypeDetailVO> settlementResult = settleAccountFeignService.findSettlementPaySetting(buyerMemberId, buyerRoleId, vendorMemberId, vendorRoleId);
        if(settlementResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(settlementResult.getCode(), settlementResult.getMessage());
        }

        //Step 1: 查询平台后台会员支付策略
        List<PlatformPayTypeBO> platformPayTypes = findPlatformMemberPayment(vendorMemberId, vendorRoleId);
        if(CollectionUtils.isEmpty(platformPayTypes)) {
            return Wrapper.success(new ArrayList<>());
        }

        //Step 2: 查询平台支付参数设置
        QPlatformPaymentParameterDO qPlatformPaymentParameter = QPlatformPaymentParameterDO.platformPaymentParameterDO;
        List<PlatformPaymentParameterDO> platformParameters = jpaQueryFactory.select(qPlatformPaymentParameter).from(qPlatformPaymentParameter)
                .where(qPlatformPaymentParameter.payChannel.in(platformPayTypes.stream().filter(payType -> payType.getFundMode().equals(FundModeEnum.PLATFORM_EXCHANGE.getCode())).flatMap(payType -> payType.getChannels().stream().map(PlatformPayChannelBO::getPayChannel)).collect(Collectors.toList())))
                .fetch();

        List<OrderPayTypeDetailVO> platformTypes = platformParameters.stream().collect(Collectors.groupingBy(PlatformPaymentParameterDO::getPayType)).entrySet().stream().map(entry -> {
            OrderPayTypeDetailVO detailVO = new OrderPayTypeDetailVO();
            detailVO.setFundMode(FundModeEnum.PLATFORM_EXCHANGE.getCode());
            detailVO.setPayType(entry.getKey());
            detailVO.setPayTypeName(OrderPayTypeEnum.getNameByCode(entry.getKey()));
            detailVO.setPayChannels(entry.getValue().stream().map(parameter ->
                    new OrderPayChannelDetailVO(parameter.getPayChannel(), OrderPayChannelEnum.getNameByCode(parameter.getPayChannel()))
            ).sorted(Comparator.comparingInt(OrderPayChannelDetailVO::getPayChannel)).collect(Collectors.toList()));
            return detailVO;
        }).collect(Collectors.toList());

        //Step 3: 查询会员支付参数设置
        QMemberPaymentParameterDO qMemberPaymentParameter = QMemberPaymentParameterDO.memberPaymentParameterDO;
        List<MemberPaymentParameterDO> memberParameters = jpaQueryFactory
                .select(qMemberPaymentParameter).from(qMemberPaymentParameter)
                .where(qMemberPaymentParameter.memberId.eq(vendorMemberId).and(qMemberPaymentParameter.roleId.eq(vendorRoleId)).and(qMemberPaymentParameter.payChannel.in(platformPayTypes.stream().filter(payType -> payType.getFundMode().equals(FundModeEnum.DIRECT_TO_ACCOUNT.getCode())).flatMap(payType -> payType.getChannels().stream().map(PlatformPayChannelBO::getPayChannel)).collect(Collectors.toList()))))
                .fetch();

        List<OrderPayTypeDetailVO> memberTypes = memberParameters.stream().collect(Collectors.groupingBy(MemberPaymentParameterDO::getPayType)).entrySet().stream().map(entry -> {
            OrderPayTypeDetailVO detailVO = new OrderPayTypeDetailVO();
            detailVO.setFundMode(FundModeEnum.DIRECT_TO_ACCOUNT.getCode());
            detailVO.setPayType(entry.getKey());
            detailVO.setPayTypeName(OrderPayTypeEnum.getNameByCode(entry.getKey()));
            detailVO.setPayChannels(entry.getValue().stream().map(parameter ->
                    new OrderPayChannelDetailVO(parameter.getPayChannel(), OrderPayChannelEnum.getNameByCode(parameter.getPayChannel()))
            ).sorted(Comparator.comparingInt(OrderPayChannelDetailVO::getPayChannel)).collect(Collectors.toList()));
            return detailVO;
        }).collect(Collectors.toList());

        //Step 4: 合并
        platformTypes.addAll(memberTypes);

        //Step 5: 账期、月结
        if(settlementResult.getData() != null) {
            platformTypes.add(settlementResult.getData());
        }

        //Step 6: 排序返回
        return Wrapper.success(platformTypes.stream().sorted(Comparator.comparingInt(OrderPayTypeDetailVO::getPayType)).collect(Collectors.toList()));
    }

    /**
     * （拆单）批量查询、校验供应商支付方式及渠道配置
     *
     * @param vendors 供应商列表
     * @return 查询结果
     */
    @Override
    public Wrapper<Map<VendorBO, List<OrderPayTypeDetailVO>>> checkMemberPayments(List<VendorBO> vendors) {
        Map<VendorBO, List<OrderPayTypeDetailVO>> paymentMap = new HashMap<>();
        for (VendorBO vendor : vendors) {
            Wrapper<List<OrderPayTypeDetailVO>> paymentResult = findMemberPayment(vendor.getVendorMemberId(), vendor.getVendorRoleId());
            if(paymentResult.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(paymentResult.getCode(), paymentResult.getMessage());
            }

            if(CollectionUtils.isEmpty(paymentResult.getData())) {
                return Wrapper.fail(ResponseCode.ORDER_SUPPLY_MEMBER_HAS_NOT_PAYMENT_SETTING);
            }

            paymentMap.put(vendor, paymentResult.getData());
        }

        return Wrapper.success(paymentMap);
    }

    /**
     * 查询支付参数
     *
     * @param payChannel 支付渠道
     * @param memberId   会员Id
     * @param roleId     会员角色Id
     * @return 支付参数
     */
    @Override
    public Wrapper<OrderPaymentParameterDetailBO> findOrderPaymentParameters(Integer payChannel, Long memberId, Long roleId) {
        //Step 1: 先查询平台支付策略配置
        List<PlatformPayTypeBO> platformPayTypes = findPlatformMemberPayment(memberId, roleId);
        if(CollectionUtils.isEmpty(platformPayTypes)) {
            return Wrapper.fail(ResponseCode.ORDER_PAYMENT_SETTING_NOT_SET_YET);
        }

        PlatformPayTypeBO platformPayType = platformPayTypes.stream().filter(payType -> payType.getChannels().stream().anyMatch(platformPayChannel -> platformPayChannel.getPayChannel().equals(payChannel))).findFirst().orElse(null);
        if(platformPayType == null) {
            return Wrapper.fail(ResponseCode.ORDER_PAYMENT_SETTING_DOES_NOT_EXIST);
        }

        //Step 2:如果支付渠道的资金归集模式是“平台代收模式”，查询平台支付参数设置
        if(platformPayType.getFundMode().equals(FundModeEnum.PLATFORM_EXCHANGE.getCode())) {
            return findPlatformPaymentParameters(payChannel);
        }

        //Step 3:如果支付渠道的资金归集模式是“会员直接到账”，查询会员支付参数设置
        return findMemberPaymentParameters(payChannel, memberId, roleId);
    }

    /**
     * 查询支付参数（直接查询平台支付参数设置）
     *
     * @param payChannel 支付渠道
     * @return 支付参数
     */
    @Override
    public Wrapper<OrderPaymentParameterDetailBO> findPlatformPaymentParameters(Integer payChannel) {
        QPlatformPaymentParameterDO qPlatformPaymentParameter = QPlatformPaymentParameterDO.platformPaymentParameterDO;
        PlatformPaymentParameterDO platformPaymentParameter = jpaQueryFactory.select(qPlatformPaymentParameter)
                .from(qPlatformPaymentParameter)
                .where(qPlatformPaymentParameter.payChannel.eq(payChannel)).fetchFirst();
        if(platformPaymentParameter == null) {
            return Wrapper.fail(ResponseCode.ORDER_PLATFORM_PARAMETER_DOES_NOT_EXIST);
        }

        return Wrapper.success(new OrderPaymentParameterDetailBO(platformPaymentParameter.getMemberId(), platformPaymentParameter.getRoleId(), FundModeEnum.PLATFORM_EXCHANGE.getCode(), platformPaymentParameter.getPayChannel(), platformPaymentParameter.getPayChannelName(), platformPaymentParameter.getParameters().stream().map(parameter -> new PayChannelParameterBO(parameter.getCode(), OrderPaymentParameterEnum.getKeyByCode(parameter.getCode()), parameter.getValue())).collect(Collectors.toList())));
    }

    /**
     * 查询支付参数（直接查询会员支付参数设置）
     *
     * @param payChannel 支付渠道
     * @param memberId   会员Id
     * @param roleId     会员角色Id
     * @return 支付参数
     */
    @Override
    public Wrapper<OrderPaymentParameterDetailBO> findMemberPaymentParameters(Integer payChannel, Long memberId, Long roleId) {
        QMemberPaymentParameterDO qMemberPaymentParameter = QMemberPaymentParameterDO.memberPaymentParameterDO;
        MemberPaymentParameterDO memberPaymentParameter = jpaQueryFactory.select(qMemberPaymentParameter)
                .from(qMemberPaymentParameter)
                .where(qMemberPaymentParameter.payChannel.eq(payChannel).and(qMemberPaymentParameter.memberId.eq(memberId)).and(qMemberPaymentParameter.roleId.eq(roleId)))
                .fetchFirst();
        if(memberPaymentParameter == null) {
            return Wrapper.fail(ResponseCode.ORDER_MEMBER_PARAMETER_DOES_NOT_EXIST);
        }

        return Wrapper.success(new OrderPaymentParameterDetailBO(memberPaymentParameter.getMemberId(), memberPaymentParameter.getRoleId(), FundModeEnum.DIRECT_TO_ACCOUNT.getCode(), memberPaymentParameter.getPayChannel(), memberPaymentParameter.getPayChannelName(), memberPaymentParameter.getParameters().stream().map(parameter -> new PayChannelParameterBO(parameter.getCode(), OrderPaymentParameterEnum.getKeyByCode(parameter.getCode()), parameter.getValue())).collect(Collectors.toList())));
    }

    /**
     * 商品能力 - 上架指引查询商品是否配置了交易流程
     *
     * @param memberId （供应商）会员Id
     * @param roleId   （供应商）会员角色Id
     * @param shopIds  商城Id列表
     * @param products 商品Id、SkuId、价格类型列表
     * @return 没有配置交易流程的商品Id、SkuId、价格类型列表
     */
    @Override
    public Wrapper<List<OrderProductProcessQueryVO>> findProductProcess(Long memberId, Long roleId, List<Long> shopIds, Integer shopType, List<OrderProductPriceTypeVO> products) {
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;

        //Step 1: 拼接会员、商品Id、SkuId查询条件
        Predicate[] predicates = products.stream().map(product ->
            qOrderTradeProcessProduct.productId.eq(product.getProductId()).and(qOrderTradeProcessProduct.skuId.eq(product.getSkuId()))
        ).toArray(Predicate[]::new);

        JPAQuery<ProductProcessBO> query = jpaQueryFactory.select(Projections.constructor(ProductProcessBO.class, qOrderTradeProcess.shopId, qOrderTradeProcess.allProducts, qOrderTradeProcessProduct.productId, qOrderTradeProcessProduct.skuId))
                .from(qOrderTradeProcess)
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrderTradeProcess.memberId.eq(memberId).and(qOrderTradeProcess.roleId.eq(roleId)).and(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode())))
                .where(qOrderTradeProcess.shopId.in(shopIds))
                .where(qOrderTradeProcess.allProducts.isTrue().or(ExpressionUtils.anyOf(predicates)));

        //根据商城类型判断交易流程类型
        OrderProductPriceTypeVO productPriceType = products.stream().findFirst().orElse(null);
        if (productPriceType != null && productPriceType.getCrossBorder() != null && productPriceType.getCrossBorder()) {
            query.where(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.ORDER_COMMERCE_IMPORT.getCode()));
        } else if (shopType.equals(ShopTypeEnum.SCORE.getCode()) || shopType.equals(ShopTypeEnum.CHANNEL_SCORE.getCode())) {
            query.where(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.RIGHT_POINT.getCode()));
        } else {
            query.where(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode()));
        }

        List<ProductProcessBO> processes = query.fetch();

        //Step 2: 如果未配置交易规则，或不是所有商城都配置了交易流程，返回所有商品
        if(CollectionUtils.isEmpty(processes) || processes.stream().anyMatch(process -> !shopIds.contains(process.getShopId()))) {
            return Wrapper.success(products.stream().map(product -> new OrderProductProcessQueryVO(product.getProductId(), product.getSkuId(), product.getPriceType())).collect(Collectors.toList()));
        }

        //Step 3: 如果所有商城都配置“适用所有商品”，返回空列表
        if(processes.stream().allMatch(ProductProcessBO::getAllProducts)) {
            return Wrapper.success(new ArrayList<>());
        }

        //Step 4: 找到没有配置交易流程的商品，返回
        return Wrapper.success(products.stream().filter(product -> processes.stream().filter(process -> !process.getAllProducts()).noneMatch(process -> process.getProductId().equals(product.getProductId()) && process.getSkuId().equals(product.getSkuId()))).map(product -> new OrderProductProcessQueryVO(product.getProductId(), product.getSkuId(), product.getPriceType())).collect(Collectors.toList()));
    }
}
